package edu.bbu.commonproject.desktop.gui.controller.utils;


import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.apache.commons.codec.binary.Base64;

/**
 * The password encrypter and decrypter class.
 */
public class CryptingService
{
	/** The key for the encrypting. */
	private final String keyString = "U$Q-[.#H:3B2o!p";
	
	/** The encrypter. */
	private Cipher encrypter;
	
	/** The decrypter. */
	private Cipher decrypter;
	
	/**
	 * The constructor.
	 * @throws InvalidKeyException if the crypting key is wrong.
	 * @throws NoSuchAlgorithmException if the algorithm does not exists.
	 * @throws UnsupportedEncodingException if the encoding fails.
	 * @throws InvalidKeySpecException if key wrong.
	 * @throws NoSuchPaddingException if pading wrong.
	 */
	public CryptingService() throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeySpecException, NoSuchPaddingException
	{
		SecretKey key = generateKey(keyString);
		
		encrypter = Cipher.getInstance("DES/ECB/PKCS5Padding");
		encrypter.init(Cipher.ENCRYPT_MODE, key);
		
		decrypter = Cipher.getInstance("DES/ECB/PKCS5Padding");
		decrypter.init(Cipher.DECRYPT_MODE, key);
	}
	
	/**
	 * Generate the key from from a key string.
	 * @param keyString the key string.
	 * @return a secret key.
	 * @throws InvalidKeyException if the crypting key is wrong.
	 * @throws NoSuchAlgorithmException if the algorithm does not exists.
	 * @throws UnsupportedEncodingException if the encoding fails.
	 * @throws InvalidKeySpecException if key wrong.
	 */
	private SecretKey generateKey(String keyString) throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeySpecException
	{
		DESKeySpec keySpec = new DESKeySpec(keyString.getBytes("UTF8")); 
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		
		return keyFactory.generateSecret(keySpec);
	}
	
	/**
	 * Encrypting the message.
	 * @param message the message string.
	 * @return encrypted message.
	 * @throws UnsupportedEncodingException if the encoding fails. 
	 * @throws IllegalBlockSizeException if the block size is bad.
	 * @throws BadPaddingException if padding wrong. 
	 */
	public String encrypt(String message) throws UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException
	{
		byte[] stringBytes = message.getBytes("UTF8");
		byte[] raw = encrypter.doFinal(stringBytes);
		
		return Base64.encodeBase64String(raw);
	}
	
	/**
	 * Describing an encrypted message.
	 * @param message the encrypted message.
	 * @return the decrypted message.
	 * @throws IllegalBlockSizeException if the block size is bad.
	 * @throws BadPaddingException if padding wrong. 
	 * @throws UnsupportedEncodingException if the encoding fails.
	 */
	public String decrypt(String message) throws IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException
	{
		byte[] raw = Base64.decodeBase64(message);
		byte[] stringBytes = decrypter.doFinal(raw);
		
		return new String(stringBytes, "UTF8");
	}
	
}

